#/usr/bin/env bash
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
#

set -u

_warn() {
	if [ $logLevel -le 2 ];then
		echo >&2 ":${BASH_SOURCE[1]}:${BASH_LINENO[0]}:Warn:$(date): $*"
	fi
}
_debug(){
	if [ $logLevel -eq 0 ];then
		echo >&2 ":${BASH_SOURCE[1]}:${BASH_LINENO[0]}:Debug:$(date): $*"
	fi
}

_die() {
	echo >&2 ":${BASH_SOURCE[1]}:${BASH_LINENO[0]}:Die:$(date): $*"
	exit 1
}
_info() {
	if [ $logLevel -le 1 ];then
		echo >&1 ":${BASH_SOURCE[1]}:${BASH_LINENO[0]}:Info:$(date): $*"
	fi
}
_wait() {
	for ((i = 0; i < ${1:-1}; i++)); do
#		echo -n "."
		sleep 1
	done
}
_sleep() {
	sleep ${1:-1}
}

init() {
	logLevel=${logLevel:-1}
	if ! type jq >/dev/null 2>&1; then
		_die "Require jq"

	fi
	if [ -z $dnsPodToken ]; then
		_die "Require dnsPodToken"
	fi
	_info bash $BASH_VERSION
        
	IPv4="(([0-9]{1,3}\.){3}[0-9]{1,3})"
	IPv6="([0-9a-fA-F]{1,4}(:{1,2})){1,15}[0-9a-fA-F]{1,4}"
	lanIPs="\
^$\
|(^10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$)\
|(^127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$)\
|(^169\.254\.[0-9]{1,3}\.[0-9]{1,3}$)\
|(^172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}$)\
|(^192\.168\.[0-9]{1,3}\.[0-9]{1,3}$)\
|(^fe80:.*$)\
"

}

check_dns() {
	local domain=$1
	local IPType=${2-IPv4}
        local dnsIPv4=A
        local dnsIPv6=AAAA
	# local IPv4="(([0-9]{1,3}\.){3}[0-9]{1,3})"
	# local IPv6="([0-9a-fA-F]{1,4}(:{1,2})){1,15}[0-9a-fA-F]{1,4}"
        host -t $(eval echo \$dns$IPType) $domain | grep -Eo "$(eval echo \$$IPType)" || _warn "Warn: Check $domain dns error"
	#if type host >/dev/null 2>&1;then
	#    if [ ${IPType} != IPv4 ];then
	#      echo -n $(host $domain |grep -Eo "${IPv6}")
	#    else
	#      echo -n $(host $domain |grep -Eo "${IPv4}")
	#    fi
	#fi
}

_dns_pod_api() {

	local agent="Ddns/0.0.1(mail@qq.com)"
	local method=${1:?'Info.Version'}
	local apiurl="https://dnsapi.cn/$method"
	local params="login_token=$dnsPodToken&format=json&$2"

	if type wget >/dev/null 2>&1; then
		wget --quiet --no-check-certificate --output-document=- --user-agent=$agent --post-data $params $apiurl || return 1
	else
		curl -s -A $agent -d $params $apiurl || return 1
	fi

}

_dnspod_getdomainid() {
	local domain=$1
	local domainid
	rs=$(_dns_pod_api "Domain.Info" "domain=${domain}")
	if [ ! -z "$rs" ] && [ "$(echo $rs | jq -r '.status.code')" = "1" ]; then
		domainid=$(echo $rs | jq -r '.domain.id')
		echo ${domainid}
	else
		_warn Get domainid \$rs empty
		return 1
	fi
}
_dnspod_getrecordid() {
	local domain=$1
	local subdomain=$2
	local DNSType=${3:-A}
	local rs
	local recordid
	rs=$(_dns_pod_api "Record.List" "domain=${domain}&sub_domain=${subdomain}")
	if [ ! -z "$rs" ] && [ "$(echo $rs | jq -r '.status.code')" = "1" ]; then
		recordid=$(echo $rs | jq -r '.records[]|select(.type=="'${DNSType}'")|.id')
		echo ${recordid}
		RECORDVALUE=$(echo $rs | jq -r '.records[]|select(.type=="'${DNSType}'")|.value')
	else
		_warn Get recordid \$rs empty
		return 1
	fi

}
_dnspod_getrecordvalue() {
	local domain=$1
	local subdomain=$2
	local DNSType=${3:-A}
	local rs
	local recordvalue
	rs=$(_dns_pod_api "Record.List" "domain=${domain}&sub_domain=${subdomain}")
	if [ ! -z "$rs" ] && [ "$(echo $rs | jq -r '.status.code')" = "1" ]; then
		recordvalue=$(echo $rs | jq -r '.records[]|select(.type=="'${DNSType}'")|.value')
		echo ${recordvalue}
	else
		_warn Get recordid \$rs empty
		return 1
	fi

}

dnspod_info() {

	local domain=$1
	local subdomain=$2
	local DNSType=${3:-A}
	local rs
	rs=$(_dns_pod_api "Domain.Info" "domain=${domain}")
	if [ ! -z "$rs" ] && [ "$(echo $rs | jq -r '.status.code')" = "1" ]; then
		DOMAINID=$(echo $rs | jq -r '.domain.id')
	else
		_warn Get domainid \$rs empty
		return 1
	fi
	rs=$(_dns_pod_api "Record.List" "domain=${domain}&sub_domain=${subdomain}")
	if [ ! -z "$rs" ] && [ "$(echo $rs | jq -r '.status.code')" = "1" ]; then
		RECORDID=$(echo $rs | jq -r '.records[]|select(.type=="'${DNSType}'")|.id')
		RECORDVALUE=$(echo $rs | jq -r '.records[]|select(.type=="'${DNSType}'")|.value')
	else
		_warn Get recordid \$rs empty
		return 1
	fi
	_info Get dns $domain ID=${DOMAINID},${subdomain} ID=${RECORDID},${subdomain}.${domain}=${RECORDVALUE},$DNSType
}

update_dns() {
	local domain=$1
	local value=$3
	local subdomain=$2
	local method="Record.Ddns"
	local DNSType=${4:-A}
	local rs
	local recordid=$(_dnspod_getrecordid "${domain}" "${subdomain}" $DNSType)
	local domainid=$(_dnspod_getdomainid ${domain})

	if [ $DNSType != "A" ]; then
		method="Record.Modify"
	fi
	rs=$(_dns_pod_api "${method}" "sub_domain=${subdomain}&domain_id=${domainid}&record_id=${recordid}&record_type=${DNSType}&value=${value}&record_line=%e9%bb%98%e8%ae%a4")
	if [ ! -z "$rs" ] && [ $(echo $rs | jq -r '.status.code') -eq 1 ]; then
		_info Update ${domainid} ${recordid} ${DNSType} ${subdomain} ${value}
	elif [ ! -z "$rs" ]; then
		_warn Update ${domainid} ${recordid} ${DNSType} ${subdomain} ${value} $(echo $rs | jq .)
		return 1
	fi
}

_get_lan_ip() {
	local device=${1:-eth0}
	local IPTYPE=${2:-IPv4}
	local hostIP
	local hostIPv6
	# 	local lanIPs="\
	# ^$\
	# |(^10\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$)\
	# |(^127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$)\
	# |(^169\.254\.[0-9]{1,3}\.[0-9]{1,3}$)\
	# |(^172\.(1[6-9]|2[0-9]|3[0-1])\.[0-9]{1,3}\.[0-9]{1,3}$)\
	# |(^192\.168\.[0-9]{1,3}\.[0-9]{1,3}$)\
	# |(^fe80:.*$)\
	# "
	# local IPv4="(([0-9]{1,3}\.){3}[0-9]{1,3})"
	# local IPv6="([0-9a-fA-F]{1,4}(:{1,2})){1,15}[0-9a-fA-F]{1,4}"
	case ${IPTYPE} in
	'IPv4')
		hostIP=$(ifconfig ${device} | grep -w inet | grep -Eoi "${IPv4}" | head -n 1)
		echo -n $hostIP
		if [ -z "${hostIP}" ]; then _warn "Error Can't get ${IPTYPE}"; fi
		;;
	'IPv6')
		hostIPv6=$(ifconfig ${device} | grep -w inet6 | grep -wEvi "fe80:" | grep -Eoi "${IPv6}" | head -n 1)
		echo -n $hostIPv6
		if [ -z "${hostIPv6}" ]; then _warn "Error Can't get ${IPTYPE}"; fi
		;;
	*)
		_warn Get lan IP IPTYPE ${IPTYPE} error
		return 1
		;;
	esac
}
get_public_ip() {
	echo -n $(curl -s http://checkip.dyndns.com | grep -Eo "(([0-9]{1,3}\.){3}[0-9]{1,3})") || (
		_warn Get public ip
		return 1
	)
}

_check_ip_type() {
	local IP=$1
	# local IPv4="(([0-9]{1,3}\.){3}[0-9]{1,3})"
	# local IPv6="([0-9a-fA-F]{1,4}(:{1,2})){1,15}[0-9a-fA-F]{1,4}"
	if [ $(echo $IP | grep -E "$IPv4") ]; then
		echo -n ipv4
	elif [ $(echo $IP | grep -E "$IPv6") ]; then
		echo -n ipv6
	else
		_warn ${IP} Check IP tyep ERROR
		return 1
		# exit 1
	fi
}

main() {
  local domain=$1
  local subdomain=$2
  local iptype=${3:-IPv4}
  local device=${4:-eth0}
  local dnsIPv4=A
  local dnsIPv6=AAAA
  local recordvalue
  local deviceip
  local dnsrecord
  local force=${5:-1}

  dnsrecord=$(check_dns ${subdomain}.${domain} $iptype)
  if [ "$device" != "wan" ]; then
    deviceip=$(_get_lan_ip $device $iptype)
    _debug Check deviceIP $deviceip
  else
    deviceip=$(get_public_ip)
  fi
  if [ ! -z ${deviceip} ] && [ "${deviceip}" = "${dnsrecord}" ] && [ ${force} -eq 1 ]; then
    _info Check ${subdomain}.${domain} $iptype ${deviceip} is ok.
  else
    recordvalue=$(_dnspod_getrecordvalue "${domain}" "${subdomain}" $(eval echo \$dns$iptype))
    if [ "${recordvalue}" != "${deviceip}" ] && [ ! -z ${deviceip} ] || [ ${force} -eq 0 ]; then
      update_dns ${domain} ${subdomain} ${deviceip} $(eval echo \$dns$iptype)
      if [ $? -eq 0 ]; then
        _info Update ${domain} ${subdomain} ${deviceip} $(eval echo \$dns$iptype) success
      fi
    fi
  fi
}

